package com.pjmike.client.netty;

import com.pjmike.client.future.DefaultFuture;
import com.pjmike.common.protocol.RpcRequest;
import com.pjmike.common.protocol.RpcResponse;
import com.pjmike.common.util.JsonUtil;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @description:
 * @author: pjmike
 * @create: 2019/03/29 11:06
 */
public class ClientHandler extends ChannelDuplexHandler {
    /**
     * 使用Map维护请求对象ID与响应结果Future的映射关系
     */
    private final Map<String, DefaultFuture> futureMap = new ConcurrentHashMap<>();

    private static final Logger log= LoggerFactory.getLogger(ClientHandler.class);

    /**
     * 客户端请求的过程：
     * 当接受到消息的时的操作：channelRead
     * 出现异常时的方法 exceptionCaught
     */

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("读取服务端返回数据");
        if (msg instanceof RpcResponse) {
            //获取响应对象
            RpcResponse response = (RpcResponse) msg;
            log.info("response  id={},error={},result={}",
                    JsonUtil.toJson(response.getRequestId()),
                    response.getError(),
                    response.getResult());
            DefaultFuture defaultFuture = futureMap.get(response.getRequestId());
            defaultFuture.setResponse(response);
        }
        super.channelRead(ctx,msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        log.info("client is exception");
        super.exceptionCaught(ctx, cause);
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        log.info("写数据请求服务端");
        if (msg instanceof RpcRequest) {
            RpcRequest request = (RpcRequest) msg;
            log.info("请求数据 id={},className={},methodName={},types={},parameters={}",
                    JsonUtil.toJson(request.getRequestId()),
                    request.getClassName(),
                    request.getMethodName(),
                    request.getParameterTypes(),
                    request.getParameters());
            //发送请求对象之前，先把请求ID保存下来，并构建一个与响应Future的映射关系
            futureMap.putIfAbsent(request.getRequestId(), new DefaultFuture());
        }
        super.write(ctx, msg, promise);
    }

    /**
     * 获取响应结果
     *
     * @param requestId
     * @return
     */
    public RpcResponse getRpcResponse(String requestId) {
        try {
            DefaultFuture future = futureMap.get(requestId);
            RpcResponse rpcResponse = future.getRpcResponse(10);
            log.info("rpcResponse={}", JsonUtil.toJson(rpcResponse));
            return  rpcResponse;
        } finally {
            //获取成功以后，从map中移除
            futureMap.remove(requestId);
        }
    }
}
